package maa.dao;

import maa.action.ActionException;
import maa.dao.h2.*;
import maa.database.ConnectionPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;

public class DAOManager {
    private static final Logger logger = LoggerFactory.getLogger(DAOManager.class);
    protected Connection connection;
    protected UserDAOimpl userDAO;
    protected CourseDAOimpl courseDAO;
    protected MentorDAOimpl mentorDAO;
    protected ClientDAOimpl clientDAO;
    protected GroupDAOimpl groupDAO;
    protected LogDAO logDAO;

    public DAOManager(Connection connection) {
        this.connection = connection;
    }

    public LogDAO getLogDAO(){
        return new LogDAO(connection);
    }

    public GroupDAOimpl getGroupDAO() {
        return new GroupDAOimpl(connection);
    }

    public UserDAOimpl getUserDAO() {
        return new UserDAOimpl(connection);
    }

    public CourseDAOimpl getCourseDAO() {
        return new CourseDAOimpl(connection);
    }

    public MentorDAOimpl getMentorDAO() {
        return new MentorDAOimpl(connection);
    }

    public ClientDAOimpl getClientDAO() {
        return new ClientDAOimpl(connection);
    }

    public Object executeAndClose(DAOCommand command) throws SQLException, ActionException {
        try{
            return command.execute(this);
        } finally {
            ConnectionPool connectionPool = ConnectionPool.getInstance();
            connectionPool.release(this.connection);
        }
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public Connection getConnection() {
        return connection;
    }

    public Object transaction(DAOCommand command) throws SQLException, ActionException {
        try{
            this.connection.setAutoCommit(false);
            Object returnValue = command.execute(this);
            this.connection.commit();
            return returnValue;
        } catch(Exception e){
            logger.error(e.getMessage());
            this.connection.rollback();
            throw e;
        } finally {
            this.connection.setAutoCommit(true);
        }
    }

    public Object transactionAndClose(final DAOCommand command) throws ActionException {
        try {
            executeAndClose(new DAOCommand(){
                public Object execute(DAOManager manager) throws ActionException {
                    try {
                        manager.transaction(command);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    return new Object();
                }

            });
        } catch (SQLException e) {
            logger.error(e.getMessage());
        }
        return new Object();
    }
}
